package com.yy.ttmodule.cardStatus;

import com.yy.ttmodule.cardStatus.SocketInterface.CommandDispatchHandler;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.net.LocalSocket;
import android.os.Message;
import android.util.Log;

public class BmWorker {

    private static final String TAG = "BmWorker";

    public int workerId;
    private Context mContext;
    private static LocalSocket mSocket;
    private CommandDispatchHandler mHandler;
    private ReceiveThread mReceiveThread;
    private SendThread mSendThread;
    private List<ByteBuffer> responseBuffers = new ArrayList<ByteBuffer>();

    private static final String PERSIST_BM_MODULE_NAME = "persist.bm.module.name";
    private static final String BM_MODULE_NAME_714 = "714";
    private static final String BM_MODULE_NAME_54 = "54";

    public BmWorker(Context context, LocalSocket socket, int workerId,
            CommandDispatchHandler handler) {
	    mContext = context;
        mSocket = socket;
        this.workerId = workerId;
        this.mHandler = handler;
        mReceiveThread = new ReceiveThread("BmWorker" + workerId
                + "ReceiveThread");
        mReceiveThread.start();
        mSendThread = new SendThread("BmWorker" + workerId + "SendThread");
        mSendThread.start();
    }

    /***循环读取消息，并分发消息***/
    private class ReceiveThread extends Thread {
        // private BufferedInputStream bis;
        private byte[] receiverBuffer = new byte[1024 * 8];

        public ReceiveThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            int length = 0;
            if (mSocket == null) {
                Log.d(TAG, "mSocket null!");
                return;
            }
            for (;;) {
                try {
                    length = readBmMessage(mSocket.getInputStream(),
                            receiverBuffer);
                    if (length < 0) {
                        break;
                    }
		            //封装byte[] -----> ByteBuffer
                    ByteBuffer msgbuf = ByteBuffer.wrap(receiverBuffer, 0,
                            length);
                    //msgbuf.flip();
                    dispatchMsg(msgbuf);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    private class SendThread extends Thread {
        private OutputStream os;
        public SendThread(String name) {
            super(name);
            try {
                os = mSocket.getOutputStream();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            for (;;) {
                if (os == null) {
                    Log.d(TAG, "mSlocket null!");
                    return;
                }
                //没有响应,则等待睡眠
                int size = responseBuffers.size();
                while (size == 0) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    synchronized(responseBuffers) {
			            size = responseBuffers.size();
		            }
                }
                //写第一个responseBuffer数据
                try {
                    os.write(responseBuffers.get(0).array());
                    //鍙戦�佹垚鍔熷悗绉婚櫎绗竴鏉℃秷鎭�
                    responseBuffers.remove(0);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    Log.e(TAG, "Response send thread write failure!");
                    e.printStackTrace();
                    try {
                        Log.e(TAG, "socket isconnected = " + mSocket.isConnected());
                        os = mSocket.getOutputStream();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        Log.e(TAG, "get New output stream Failure!!!");
                    }
                }
            }
        }
    }

    //分发处理消息(保密命令)
    public void dispatchMsg(ByteBuffer buf) {
        if ((buf == null) || (buf.remaining() < 4)) {
            Log.d(TAG, "dispatchMsg,parm wrong!");
            return;
        }
        int msgId = buf.getInt();
        Log.d(TAG, "msgId = " + msgId);
        switch (msgId) {
            case BmCommandId.ID_GET_BM_CARD_STATE:
                getBmCardState(BmCommandId.ID_GET_BM_CARD_STATE);
                break;
            case BmCommandId.ID_GET_BM_BAR_START:
                getBmBarState(BmCommandId.ID_GET_BM_BAR_START);
                break;
            case BmCommandId.ID_DESTROY_KEY:
                destroyKey(BmCommandId.ID_DESTROY_KEY);
                break;
            case BmCommandId.ID_SWITCH_BM_CHANNEL:
                byte flag = buf.get();
                bmChannelSwitch(flag == 1?true:false);
                break;
            case BmCommandId.ID_SET_BM_CARD_STATE:{
                setBmCardMode(BmCommandId.ID_SET_BM_CARD_STATE, 1);
                break;
                }
            case BmCommandId.ID_GET_BM_CARD_POWER_ON_STATE:{
                getBmCardPowerOnState(BmCommandId.ID_GET_BM_CARD_POWER_ON_STATE);
                break;
            }
        }

    }
    //发送AT命令,获取(保密卡状态)
    private void getBmCardState(int reqId) {
        String atCmdBmCard = "AT+SECARD=1\r\n";
        String moduleName = getProp(PERSIST_BM_MODULE_NAME, BM_MODULE_NAME_714);
        Log.i(TAG, "moduleName = " + moduleName);
        if (BM_MODULE_NAME_714.equals(moduleName)) {
            atCmdBmCard = "AT+SMD=1\r\n";
        } else if (BM_MODULE_NAME_54.equals(moduleName)) {
            atCmdBmCard = "AT+SECARD=1\r\n";
        }
	    Log.i(TAG, "atCmdBmCard="+atCmdBmCard);
        Command command = new Command(workerId,reqId, atCmdBmCard);
        Message msg = new Message();
        msg.what = SocketInterface.MSG_ID_SEND_COMMAND;
        msg.obj = command;
        mHandler.sendMessage(msg);
    }

    //发送AT命令,获取保密棒状态
    private void getBmBarState(int reqId) {
        String atCmdBmBar = "AT+SECARD=2\r\n";
        String moduleName = getProp(PERSIST_BM_MODULE_NAME, BM_MODULE_NAME_714);
        Log.i(TAG, "moduleName = " + moduleName);
        if (BM_MODULE_NAME_714.equals(moduleName)) {
            atCmdBmBar = "AT+SMD=3\r\n";
        } else if (BM_MODULE_NAME_54.equals(moduleName)) {
            atCmdBmBar = "AT^BMCKEYS\r\n";
        }
        Log.i(TAG, "atCmdBmBar = " + atCmdBmBar);
        Command command = new Command(workerId,reqId, atCmdBmBar);
        Message msg = new Message();
        msg.what = SocketInterface.MSG_ID_SEND_COMMAND;
        msg.obj = command;
        mHandler.sendMessage(msg);
    }

    //保密卡模式设置(54)
    private void setBmCardMode(int reqId, int mode) {
        String moduleName = getProp(PERSIST_BM_MODULE_NAME, BM_MODULE_NAME_714);
        Log.i(TAG, "moduleName = " + moduleName);
        String atCmdBmBar = "";
        if (BM_MODULE_NAME_54.equals(moduleName)) {
            atCmdBmBar = "AT^BMCMODES=" + mode + "\r\n";
            Command command = new Command(workerId,reqId, atCmdBmBar);
            Message msg = new Message();
            msg.what = SocketInterface.MSG_ID_SEND_COMMAND;
            msg.obj = command;
            mHandler.sendMessage(msg);
        }
    }
    //上电查询(54)
    private void getBmCardPowerOnState(int reqId) {
        String moduleName = getProp(PERSIST_BM_MODULE_NAME, BM_MODULE_NAME_714);
        Log.i(TAG, "moduleName = " + moduleName);
        String atCmdBmBar = "";
        if (BM_MODULE_NAME_54.equals(moduleName)) {
            atCmdBmBar = "AT^BMCPWRC\r\n";
            Command command = new Command(workerId,reqId, atCmdBmBar);
            Message msg = new Message();
            msg.what = SocketInterface.MSG_ID_SEND_COMMAND;
            msg.obj = command;
            mHandler.sendMessage(msg);
        }
    }
    
    //发送AT命令,销毁密钥
    private void destroyKey(int reqId) {
        Command command = new Command(workerId, reqId, "AT+SECARD=3\r\n");
        Message msg = new Message();
        msg.what = SocketInterface.MSG_ID_SEND_COMMAND;
        msg.obj = command;
        mHandler.sendMessage(msg);
    }
    //读取保密消息(消息长度+消息数据)
    private int readBmMessage(InputStream is, byte[] buffer) throws IOException {
        int countRead = 0;
        int offset = 0;
        int remaining = 4;
        int messageLength = 0;
        // First, read in the length of the message
	//        offset = 0;
	//        remaining = 4;
        do {
            countRead = is.read(buffer, offset, remaining);
            if (countRead < 0) {//读取出错
                Log.e(TAG, "Hit EOS reading message length");
                Message msg = new Message();
                msg.what = SocketInterface.MSG_ID_REMOVE_WORKER;
                msg.obj = BmWorker.this;
                mHandler.sendMessage(msg);
                return -1;
            }
            offset += countRead;
            remaining -= countRead;
        } while (remaining > 0);
	    //大端; 消息长度
        messageLength = ((buffer[0] & 0xff) << 24) | ((buffer[1] & 0xff) << 16)
                | ((buffer[2] & 0xff) << 8) | (buffer[3] & 0xff);

        // Then, re-use the buffer and read in the message itself
        offset = 0;
        remaining = messageLength;
        do {//读取消息数据
            countRead = is.read(buffer, offset, remaining);

            if (countRead < 0) {
                Log.e(TAG, "Hit EOS reading message.  messageLength="
                        + messageLength + " remaining=" + remaining);
                
                return -1;
            }
            offset += countRead;
            remaining -= countRead;
        } while (remaining > 0);
        return messageLength;
    }

    //发送命令
    public void sendResponse(Command command) {
        // TODO Auto-generated method stub
        if (command == null) {
            Log.d(TAG, "sendResponse, command null!");
            return;
        }
        Log.d(TAG, "workid = " + command.getWorkerId() + 
                        "response = " + command.getResponse() +
                        "reqId = " + command.getReqId());
        ByteBuffer msgBuffer = createResponseSocketMsg(command);
        if (msgBuffer != null) {
            synchronized(responseBuffers) {
                responseBuffers.add(msgBuffer);
            }
        }
        
    }

    //创建响应socket的消息
    public ByteBuffer createResponseSocketMsg(Command command) {
        if (command.getResponse() == null) {
            return null;
        }
        byte[] msgBody = command.getResponse().getBytes();
        //4bytes msgLength,4byte msgID
        ByteBuffer buf = ByteBuffer.allocate(4 + 4 + msgBody.length);
        int msgLength = msgBody.length + 4;
        buf.putInt(msgLength);
        buf.putInt(command.getReqId());
        buf.put(msgBody);
        return buf;
    }
    
    private static final String BM_CHANNEL_SWITCH_FILE = "/sys/misc-config/usb_id_sw";
    
    //创建通道切换响应
    private Command createBmChannelSwitchResponse(String response) {
    	Command command = new Command(this.workerId, BmCommandId.ID_SWITCH_BM_CHANNEL, "");
    	command.setResponse(response);
    	return command;
    }

    // 保密通道切换，并发送响应消息
    public void bmChannelSwitch(boolean isOpen) {
    	Command command = null;
    	try {
			FileWriter fw = new FileWriter(BM_CHANNEL_SWITCH_FILE);
			if (isOpen) {
				fw.write("1");
			} else {
				fw.write("0");
			}
			fw.flush();
			fw.close();
			command = createBmChannelSwitchResponse("ok");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			 Log.d(TAG,"switch failure");
			e.printStackTrace();
			command = createBmChannelSwitchResponse("error");
		}
    	sendResponse(command);
    }

    public String getProp(String key, String defaultValue) {
        String value = defaultValue;
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class, String.class);
            value = (String) (get.invoke(c, key, defaultValue));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return value;
        }
    }

}
